// useless.cpp -- an otherwise useless class with move semantics
//#include <iostream>
//using namespace std;
//
//// interface
//class Useless
//{
//private:
//	int n;			// number of elements
//	char* pc;		// pointer to data
//	static int ct;	// number of objects
//	void ShowObject() const;
//
//public:
//	Useless();
//	explicit Useless(int k);
//	Useless(int k, char ch);
//	Useless(const Useless& f);	// regular copy constructor
//	Useless(Useless&& f);		// move constructor
//	~Useless();
//	Useless operator+(const Useless& f) const;
//	// need operator=() in copy and move versions
//	void ShowData() const;
//};
//
//// implementation
//int Useless::ct = 0;
//
//Useless::Useless()
//{
//	++ct;
//	n = 0;
//	pc = nullptr;
//	cout << "default constructor called; number of objects: " << ct << endl;
//	ShowObject();
//}
//
//Useless::Useless(int k) :n(k)
//{
//	++ct;
//	cout << "int constructor called; number of objects: " << ct << endl;
//	pc = new char[n];
//	ShowObject();
//}
//
//Useless::Useless(int k, char ch) :n(k)
//{
//	++ct;
//	cout << "int, char constructor called; number of objects: " << ct
//		 << endl;
//	pc = new char[n];
//	for (int i = 0; i < n; i++)
//	{
//		pc[i] = ch;
//	}
//	ShowObject();
//}
//
//Useless::Useless(const Useless& f) :n(f.n)
//{
//	++ct;
//	cout << "copy const called; number of objects: " << ct << endl;
//	pc = new char[n];
//	for (int i = 0; i < n; i++)
//	{
//		pc[i] = f.pc[i];
//	}
//	ShowObject();
//}
//
//Useless::Useless(Useless&& f) :n(f.n)
//{
//	++ct;
//	cout << "move constructor called; number of objects: " << ct << endl;
//	pc = f.pc;		// steal address
//	f.pc = nullptr;	// give old object nothing in return
//	f.n = 0;
//	ShowObject();
//}
//
//Useless::~Useless()
//{
//	cout << "destructor called; objects left: " << --ct << endl;
//	cout << "deleted object:\n";
//	ShowObject();
//	delete[] pc;
//}
//
//Useless Useless::operator+(const Useless& f) const
//{
//	cout << "Entering operator+()\n";
//	Useless temp = Useless(n + f.n);
//	for (int i = 0; i < n; i++)
//	{
//		temp.pc[i] = pc[i];
//	}
//	for (int i = n; i < temp.n; i++)
//	{
//		temp.pc[i] = f.pc[i - n];
//	}
//	cout << "temp object:\n";
//	cout << "Leaving operator+()\n";
//	return temp;
//}
//
//void Useless::ShowObject() const
//{
//	cout << "Number of elements: " << n;
//	cout << " Data address: " << (void*)pc << endl;
//}
//
//void Useless::ShowData() const
//{
//	if (n == 0)
//	{
//		cout << "(object empty)";
//	}
//	else
//	{
//		for (int i = 0; i < n; i++)
//		{
//			cout << pc[i];
//		}
//	}
//	cout << endl;
//}
//
//// application
//int main()
//{
//	{
//		Useless one(10, 'x');
//		Useless two = one;			// calls copy constructor
//		Useless three(20, 'o');
//		Useless four(one + three);	// class operator+(), move constructor
//		cout << "object one: ";
//		one.ShowData();
//		cout << "object two: ";
//		two.ShowData();
//		cout << "object three: ";
//		three.ShowData();
//		cout << "object four: ";
//		four.ShowData();
//	}
//
//	return 0;
//}

// lambda1.cpp -- use capture variables
//#include <iostream>
//#include <vector>
//#include <algorithm>
//#include <cmath>
//#include <ctime>
//
//const long Size = 390000L;
//
//int main()
//{
//	using std::cout;
//	std::vector<int> numbers(Size);
//
//	std::srand(std::time(0));
//	std::generate(numbers.begin(), numbers.end(), std::rand);
//	cout << "Sample size = " << Size << '\n';
//
//	// using lambdas
//	int count3 = std::count_if(numbers.begin(), numbers.end(),
//		[](int x) {return x % 3 == 0; });
//	cout << "Count of numbers divisible by 3: " << count3 << '\n';
//	int count13 = 0;
//	std::for_each(numbers.begin(), numbers.end(),
//		[&count13](int x) {count13 += x % 13 == 0; });
//	cout << "Count of numbers divisible by 13: " << count13 << '\n';
//
//	// using a single lambda
//	count3 = count13 = 0;
//	std::for_each(numbers.begin(), numbers.end(),
//		[&](int x) {count3 += x % 3 == 0; count13 += x % 13 == 0; });
//	cout << "Count of numbers divisible by 3: " << count3 << '\n';
//	cout << "Count of numbers divisible by 13: " << count13 << '\n';
//
//	return 0;
//}

// somedefs.h
//#include <iostream>
//
//template<typename T, typename F>
//T use_f(T v, F f)
//{
//	static int count = 0;
//	count++;
//	std::cout << " use_f count = " << count
//			  << ", &count = " << &count << std::endl;
//	return f(v);
//}
//
//class Fp
//{
//private:
//	double z_;
//public:
//	Fp(double z = 1.0) :z_(z) {}
//	double operator()(double p) { return z_ * p; }
//};
//
//class Fq
//{
//private:
//	double z_;
//public:
//	Fq(double z = 1.0) :z_(z) {}
//	double operator()(double p) { return z_ + p; }
//};
//
//// wrapped.cpp -- using a function wrapper as an argument
//#include <functional>
//
//double dub(double x) { return 2.0 * x; }
//double square(double x) { return x * x; }
//
//int main()
//{
//	using std::cout;
//	using std::endl;
//	using std::function;
//
//	double y = 1.21;
//	function<double(double)> ef1 = dub;
//	function<double(double)> ef2 = square;
//	function<double(double)> ef3 = Fp(10.0);
//	function<double(double)> ef4 = Fq(10.0);
//	function<double(double)> ef5 = [](double u) { return u * u; };
//	function<double(double)> ef6 = [](double u) { return u + u / 2.0; };
//
//	cout << "Function pointer dub:\n";
//	cout << " " << use_f(y, ef1) << endl;
//	cout << "Function pointer square:\n";
//	cout << " " << use_f(y, ef2) << endl;
//	cout << "Function object Fp:\n";
//	cout << " " << use_f(y, ef3) << endl;
//	cout << "Function object fq:\n";
//	cout << " " << use_f(y, ef4) << endl;
//	cout << "Lambda expressino 1:\n";
//	cout << " " << use_f(y, ef5) << endl;
//	cout << "Lambda expressino 2:\n";
//	cout << " " << use_f(y, ef6) << endl;
//
//	return 0;
//}

// variadic2.cpp
#include <iostream>
#include <string>

// definition for 0 parameters
void show_list() {}

// definition for 1 parameters
template<typename T>
void show_list(const T& value)
{
	std::cout << value << '\n';
}

// definition for 2 or more parameters
template<typename T, typename... Args>
void show_list(const T& value, const Args&... args)
{
	std::cout << value << ", ";
	show_list(args...);
}

int main()
{
	int n = 14;
	double x = 2.71828;
	std::string mr = "Mr. String objects!";
	show_list(n, x);
	show_list(x * x, '!', 7, mr);

	return 0;
}